/*************************************************************************
	> File Name: 016.Kruskal.cpp
	> Author: Maureen 
	> Mail: Maureen@qq.com 
	> Created Time: 五  6/25 19:11:44 2021
 ************************************************************************/

#include <iostream>
#include <algorithm>
using namespace std;

//Kruskal算法求解最小生成树
//可用“P3366【模板】最小生成树” 验证

struct edge {
    int s, e, v;
    bool operator<(const edge &b) const {
        return this->v < b.v;
    }
};

edge edg[400005];
int n, m, ans, my_union[5005]; //并查集
int cnt = 1; //cnt记录并查集中边的数量 

int find_fa(int x) {
    if (my_union[x] == x) {
        return x;
    }
    return my_union[x] = find_fa(my_union[x]); //路径压缩
}

int main() {
    cin >> n >> m;
    for (int i = 1; i <= n; i++) {
        my_union[i] = i;
    }
    for (int i = 0; i < m; i++) {
        cin >> edg[i].s >> edg[i].e >> edg[i].v;
    }
    sort(edg, edg + m);
    for (int i = 0; i < m; i++) {
        //查找起点和终点所属的并查集
        int fa = find_fa(edg[i].s), fb = find_fa(edg[i].e);
        if (fa != fb) { //不在同一个并查集中, 两点之间的边要加到结果中
            ans += edg[i].v;
            my_union[fa] = fb; //合并并查集
            cnt++;
            if (cnt == n) {
                break;
            }
        }
    }
    if (cnt == n) {
        cout << ans << endl;
    } else {
        cout << "orz" << endl;
    }

    return 0;
}
